// Copyright (c) 2010. Eric Nelson  
// https://code.google.com/p/prompts/
// All rights reserved.
//     
// Redistribution and use in source and binary forms,   
// with or without modification, are permitted provided   
// that the following conditions are met:    
// * Redistributions of source code must retain the   
// above copyright notice, this list of conditions and   
// the following disclaimer.    
// * Redistributions in binary form must reproduce   
// the above copyright notice, this list of conditions   
// and the following disclaimer in the documentation   
// and/or other materials provided with the distribution.    
// * Neither the name of Eric Nelson nor the   
// names of its contributors may be used to endorse   
// or promote products derived from this software   
// without specific prior written permission.    
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND   
// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,   
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF   
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE   
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR   
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,   
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,   
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR   
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS   
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,   
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING   
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE   
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF   
// SUCH DAMAGE.
// 
//     
// [This is the BSD license, see  
// http://www.opensource.org/licenses/bsd-license.php]  
using System;
using System.Collections.ObjectModel;
using Prompts.Prompting.Construction;
using Prompts.Prompting.Model;

namespace Prompts.Prompting.ViewModels.Implementation
{
    public class ChildTreeNodeService : IChildTreeNodeService
    {
        private readonly ITreeNodeCollectionBuilder _treeNodeCollectionBuilder;
        private readonly IChildPromptLevelServiceClient _childPromptLevelService;

        public ChildTreeNodeService(IChildPromptLevelServiceClient childPromptLevelService, ITreeNodeCollectionBuilder treeNodeCollectionBuilder)
        {
            _childPromptLevelService = childPromptLevelService;
            _treeNodeCollectionBuilder = treeNodeCollectionBuilder;

            _childPromptLevelService.GetChildrenForCompleted += OnGetChildrenForCompleted;
        }

        public void GetChildrenFor(string promptName, string parameterName, ITreeNode treeNode, Action<ObservableCollection<ITreeNode>> result)
        {
            var helper = new GetChildPromptValuesHelper(treeNode, promptName, result);

            _childPromptLevelService.GetChildrenForAsync(
                promptName
                , parameterName
                , treeNode.GetParameterValueHierarchy()
                , helper);
        }

        private void OnGetChildrenForCompleted(object sender, GetChildrenForCompletedEventArgs e)
        {
            var helper = (GetChildPromptValuesHelper)e.UserState;

            var treeNodes = _treeNodeCollectionBuilder.BuildRegularNodesFrom(
                helper.PromptName
                , e.Result.ParameterName
                , e.Result.AvailableItems
                , helper.ParentTreeNode
                , e.Result.HasChildLevel);

            helper.CallBack(treeNodes);
        }

        private class GetChildPromptValuesHelper
        {
            private readonly ITreeNode _parentTreeNode;
            private readonly string _promptName;
            private readonly Action<ObservableCollection<ITreeNode>> _callBack;

            public GetChildPromptValuesHelper(ITreeNode parentTreeNode, string promptName, Action<ObservableCollection<ITreeNode>> callBack)
            {
                _callBack = callBack;
                _parentTreeNode = parentTreeNode;
                _promptName = promptName;
            }

            public string PromptName
            {
                get { return _promptName; }
            }

            public Action<ObservableCollection<ITreeNode>> CallBack
            {
                get { return _callBack; }
            }

            public ITreeNode ParentTreeNode
            {
                get { return _parentTreeNode; }
            }
        }
    }
}